package com.njworkorder.Controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.njworkorder.DTO.AdministrativePersonnelAddDto;
import com.njworkorder.Entity.*;
import com.njworkorder.Service.AdministrativePersonnelService;
import com.njworkorder.Service.ApRoleService;
import com.njworkorder.Service.PatrolInfoService;
import com.njworkorder.Service.SysVisitsService;
import com.njworkorder.Utils.MD5Util;
import com.njworkorder.Utils.Result;
import com.njworkorder.Utils.ResultUtil;
import com.njworkorder.Utils.WebClientUtil;
import com.njworkorder.VO.ApListVo;
import com.njworkorder.VO.FinancialProgressVo;
import com.njworkorder.VO.LngLat;
import com.njworkorder.VO.LoginVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Tag(name = "行政人员接口", description = "行政人员相关接口")
@RestController
@RequestMapping("/ap")
public class APController {

    private final AdministrativePersonnelService administrativePersonnelService;
    private final ApRoleService apRoleService;
    private final SysVisitsService sysVisitsService;
    private final PatrolInfoService  patrolInfoService;
    public APController(AdministrativePersonnelService administrativePersonnelService,
                        ApRoleService apRoleService, SysVisitsService sysVisitsService,PatrolInfoService  patrolInfoService) {
        this.administrativePersonnelService = administrativePersonnelService;
        this.apRoleService = apRoleService;
        this.sysVisitsService = sysVisitsService;
        this.patrolInfoService = patrolInfoService;
    }

    @Operation(summary = "添加行政人员信息")
    @PostMapping("/addInfo")
    public Result<String> addInfo(@RequestBody AdministrativePersonnelAddDto administrativePersonnelAddDto,
                                  @RequestHeader("Create-Ap-Id") String createApId){

        LambdaQueryWrapper<AdministrativePersonnel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(AdministrativePersonnel::getUid,administrativePersonnelAddDto.getUid());
        long count = administrativePersonnelService.count(lambdaQueryWrapper);
        if (count>0){
            return ResultUtil.fail("用户名已存在!");
        }

        AdministrativePersonnel AP = new AdministrativePersonnel();
        BeanUtils.copyProperties(administrativePersonnelAddDto,AP);
        String id = UUID.randomUUID().toString();
        AP.setId(id);
        AP.setXzryid(id);
        AP.setPassword(MD5Util.encrypt(administrativePersonnelAddDto.getPassword()));
        AP.setModTime(new Date());
        AP.setCreateApId(createApId);

        if(StringUtils.isNotEmpty(administrativePersonnelAddDto.getRoleId())){
            saveAPRole(administrativePersonnelAddDto.getRoleId(), id);
        }


        boolean save = administrativePersonnelService.save(AP);
        if (save){
            return ResultUtil.success("添加成功");
        }
        return ResultUtil.fail("添加失败");
    }

    @Operation(summary = "根据id删除行政人员信息")
    @GetMapping("/deleteInfo")
    public Result<String> deleteInfo(@RequestParam("id") String id){

        LambdaQueryWrapper<ApRole> queryWrapper = new LambdaQueryWrapper<ApRole>()
                .eq(ApRole::getApId,id);
        apRoleService.remove(queryWrapper);

        boolean removeById = administrativePersonnelService.removeById(id);
        if (removeById){
            return ResultUtil.success("删除成功");
        }
        return ResultUtil.fail("删除失败");
    }

    @Transactional
    @Operation(summary = "根据id修改行政人员信息")
    @PostMapping("/updateInfoById/{id}")
    public Result<String> updateInfo(@RequestBody AdministrativePersonnelAddDto APAddDto,
                                     @PathVariable("id") String id){

        LambdaUpdateWrapper<AdministrativePersonnel> lambdaUpdateWrapper = new LambdaUpdateWrapper<AdministrativePersonnel>()
                .set(AdministrativePersonnel::getModTime,new Date())
                .set(StringUtils.isNotEmpty(APAddDto.getOrganizationId()),AdministrativePersonnel::getOrganizationId,APAddDto.getOrganizationId())
                .set(StringUtils.isNotEmpty(APAddDto.getUid()),AdministrativePersonnel::getUid,APAddDto.getUid())
                .set(StringUtils.isNotEmpty(APAddDto.getName()),AdministrativePersonnel::getName,APAddDto.getName())
                .set(StringUtils.isNotEmpty(APAddDto.getGender()),AdministrativePersonnel::getGender,APAddDto.getGender())
                .set(StringUtils.isNotEmpty(APAddDto.getType()),AdministrativePersonnel::getType,APAddDto.getType())
                .set(StringUtils.isNotEmpty(APAddDto.getAvatar()),AdministrativePersonnel::getAvatar,APAddDto.getAvatar())
                .set(StringUtils.isNotEmpty(APAddDto.getEmail()),AdministrativePersonnel::getEmail,APAddDto.getEmail())
                .set(StringUtils.isNotEmpty(APAddDto.getStatus()),AdministrativePersonnel::getStatus,APAddDto.getStatus())
                .eq(AdministrativePersonnel::getId,id);


        if(StringUtils.isNotEmpty(APAddDto.getRoleId())){
            LambdaQueryWrapper<ApRole> queryWrapper = new LambdaQueryWrapper<ApRole>()
                    .eq(ApRole::getApId,id);
            apRoleService.remove(queryWrapper);

            saveAPRole(APAddDto.getRoleId(), id);
        }

        boolean b = administrativePersonnelService.update(lambdaUpdateWrapper);
        if (b){
            return ResultUtil.success("修改成功");
        }
        return ResultUtil.fail("修改失败");
    }


    @Operation(summary = "根据id查询行政人员信息")
    @GetMapping("/queryInfo")
    public Result<AdministrativePersonnel> queryInfo(@RequestParam("id") String id){
        AdministrativePersonnel list = administrativePersonnelService.getById(id);
        return ResultUtil.success(list);
    }

    @Operation(summary = "查询行政人员信息列表")
    @GetMapping("/getList")
    public Result<Page<ApListVo>> getList(@RequestParam("pageIndex") int pageIndex, @RequestParam("pageSize") int pageSize) {

        MPJLambdaWrapper<AdministrativePersonnel> wrapper = new MPJLambdaWrapper<AdministrativePersonnel>()
                .selectAll(AdministrativePersonnel.class)
                .leftJoin(AdministrativeOrganization.class,AdministrativeOrganization::getId,AdministrativePersonnel::getOrganizationId,ext ->
                        ext.selectAs(AdministrativeOrganization::getName, ApListVo::getOrganizationName))
//                .leftJoin(Role.class,Role::getId,AdministrativePersonnel::getRoleId,ext ->
//                        ext.selectAs(Role::getRoleName, ApListVo::getRoleName))
                .leftJoin(AdministrativePersonnel.class, AdministrativePersonnel::getId,AdministrativePersonnel::getCreateApId,ext ->
                        ext.selectAs(AdministrativePersonnel::getName, ApListVo::getCreateApName))
                .apply("1=1");
        Page<ApListVo> apListVoPage = administrativePersonnelService.selectJoinListPage(new Page<>(pageIndex, pageSize), ApListVo.class, wrapper);


        if (pageSize <= 100) {
            MPJLambdaWrapper<ApRole> wrapper1 = new MPJLambdaWrapper<ApRole>()
                    .select(ApRole::getApId)
                    .selectAs(Role::getRoleName,ApRole::getRoleId)
                    .leftJoin(Role.class,Role::getId,ApRole::getRoleId)
                    .in(ApRole::getApId,apListVoPage.getRecords().stream().map(ApListVo::getId).toList())
                    .apply("1=1");
            List<ApRole> list = apRoleService.list(wrapper1);

            for(ApListVo item : apListVoPage.getRecords()){
                List<ApRole> list1 = list.stream().filter(f -> f.getApId().equals(item.getId())).toList();
                if(!list1.isEmpty()){
                    String collect = list1.stream().map(ApRole::getRoleId).collect(Collectors.joining(","));
                    item.setRoleName(collect);
                }
            }
        }

        return ResultUtil.success(apListVoPage);
    }


    @Operation(summary = "根据组织id查询行政人员信息列表")
    @GetMapping("/getListByOrgId")
    public Result<Page<AdministrativePersonnel>> getListByOrgId(@RequestParam("pageIndex") int pageIndex,
                                                                @RequestParam("pageSize") int pageSize,
                                                                @RequestParam(value = "status",required = false) String status,
                                                                @Schema(description = "组织id") @RequestParam(value = "orgId") String orgId,
                                                                @Schema(description = "grade") @RequestParam(value = "grade",required = false) String grade,
                                                                @Schema(description = "用户名") @RequestParam(value = "uid",required = false) String uid,
                                                                @Schema(description = "姓名") @RequestParam(value = "name",required = false) String name) {

        if(grade != null){
            switch (grade){
                case "2":
                    MPJLambdaWrapper<AdministrativePersonnel> wrapper2 = new MPJLambdaWrapper<AdministrativePersonnel>()
                            .select(AdministrativePersonnel::getId, AdministrativePersonnel::getName,AdministrativePersonnel::getUid,
                                    AdministrativePersonnel::getXzryid,AdministrativePersonnel::getOrganizationId,
                                    AdministrativePersonnel::getGender,AdministrativePersonnel::getStatus,AdministrativePersonnel::getPublishTime)
                            .leftJoin(AoAp.class,AoAp::getUuid,AdministrativePersonnel::getXzryid)
                            .leftJoin(AdministrativeOrganization.class,AdministrativeOrganization::getXzzzid,AoAp::getOuid)
                            .eq(AdministrativeOrganization::getParentId,orgId)
                            .groupBy(AdministrativePersonnel::getXzryid);
                    return ResultUtil.success(administrativePersonnelService.page(new Page<>(pageIndex, pageSize), wrapper2));
                case "3" :
                    MPJLambdaWrapper<AdministrativePersonnel> wrapper3 = new MPJLambdaWrapper<AdministrativePersonnel>()
                            .select(AdministrativePersonnel::getId, AdministrativePersonnel::getName,AdministrativePersonnel::getUid,
                                    AdministrativePersonnel::getXzryid,AdministrativePersonnel::getOrganizationId,
                                    AdministrativePersonnel::getGender,AdministrativePersonnel::getStatus,AdministrativePersonnel::getPublishTime)
                            .leftJoin(AoAp.class,AoAp::getUuid,AdministrativePersonnel::getXzryid)
                            .eq(AoAp::getOuid,orgId);
                    return ResultUtil.success(administrativePersonnelService.page(new Page<>(pageIndex, pageSize), wrapper3));
            }
        }

        LambdaQueryWrapper<AdministrativePersonnel> wrapper = new LambdaQueryWrapper<AdministrativePersonnel>()
                .select(AdministrativePersonnel::getId, AdministrativePersonnel::getName,AdministrativePersonnel::getUid,
                        AdministrativePersonnel::getXzryid,AdministrativePersonnel::getOrganizationId,
                        AdministrativePersonnel::getGender,AdministrativePersonnel::getStatus,AdministrativePersonnel::getPublishTime)
                .eq(AdministrativePersonnel::getOrganizationId, orgId)
                .eq(StringUtils.isNotEmpty(status), AdministrativePersonnel::getStatus, status)
                .eq(StringUtils.isNotEmpty(uid), AdministrativePersonnel::getUid, uid)
                .eq(StringUtils.isNotEmpty(name), AdministrativePersonnel::getName, name)
                .orderByDesc(AdministrativePersonnel::getPublishTime);
        return ResultUtil.success(administrativePersonnelService.page(new Page<>(pageIndex, pageSize), wrapper));

    }

    @Parameters({
            @Parameter(name = "uId", description = "用户名", required = true),
            @Parameter(name = "password", description = "密码",required = true)
    })
    @Operation(summary = "行政人员登录")
    @GetMapping("/apLogin")
    public Result<LoginVo> apLogin(@RequestParam("uId") String uId, @RequestParam("password") String pwd){
        LambdaQueryWrapper<AdministrativePersonnel> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdministrativePersonnel::getUid, uId);
        AdministrativePersonnel list = administrativePersonnelService.getOne(wrapper);

        if (list != null){
            if(MD5Util.encrypt(pwd).equals(list.getPassword())){
                CompletableFuture<LoginVo> loginVoByUid = administrativePersonnelService.getLoginVoByUid(uId);
                CompletableFuture<List<ApRole>> apRoleByApId = apRoleService.getApRoleByApId(list.getId());

                CompletableFuture.allOf(apRoleByApId,loginVoByUid).join();
                List<ApRole> apRoleList = apRoleByApId.join();

                if(apRoleList.isEmpty()){
                    return ResultUtil.fail("用户还没有分配角色！");
                }

                //异步添加访问量
                sysVisitsService.incrementField();

                LoginVo loginVo = loginVoByUid.join();
                String collect = apRoleList.stream().map(ApRole::getRoleId).collect(Collectors.joining(","));
                loginVo.setRoleId(collect);
                return ResultUtil.success(loginVo);
            }
            return ResultUtil.fail("密码错误！");
        }
        return ResultUtil.fail("用户名不存在！");
    }

    @Operation(summary = "根据id修改密码")
    @GetMapping("/updatePwdById")
    public Result<String> updatePwdById(@RequestParam("id") String id,
                                        @RequestParam("newPwd") String newPwd,
                                        @RequestParam("oldPwd") String oldPwd) {


        LambdaQueryWrapper<AdministrativePersonnel> queryWrapper = new LambdaQueryWrapper<AdministrativePersonnel>()
                .eq(AdministrativePersonnel::getId, id).eq(AdministrativePersonnel::getPassword,  MD5Util.encrypt(oldPwd));
        long count = administrativePersonnelService.count(queryWrapper);
        if(count == 0){return ResultUtil.fail("旧密码输入错误！");}


        LambdaUpdateWrapper<AdministrativePersonnel> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(AdministrativePersonnel::getId, id).set(AdministrativePersonnel::getPassword, MD5Util.encrypt(newPwd));
        boolean update = administrativePersonnelService.update(wrapper);
        if (update) {
            return ResultUtil.success("修改成功");
        }
        return ResultUtil.fail("修改失败");
    }


    @Operation(summary = "给用户分配角色")
    @GetMapping("/assigningRoles")
    public Result<String> assigningRoles(@RequestParam("apId") String apId,
                                         @RequestParam("roleId") String roleId) {
        boolean b = saveAPRole(roleId, apId);
        if (b) {
            return ResultUtil.success("分配成功");
        }
        return ResultUtil.fail("分配失败");
    }

    private boolean saveAPRole(String roleIds,String apId){
        String[] split = roleIds.split(",");
        List<ApRole> apRoleList = new ArrayList<>();
        ApRole apRole;
        for (String s : split) {
            apRole = new ApRole();
            apRole.setApId(apId);
            apRole.setRoleId(s);
            apRoleList.add(apRole);
        }
        return apRoleService.saveBatch(apRoleList);
    }

    @Operation(summary = "获取系统访问量次数")
    @GetMapping("/getSysVisits")
    public Result<Map<String,Object>> getSysVisits(@RequestParam(value = "days",required = false,defaultValue = "7") int days) throws ParseException {

        Map<String,Object> map = new HashMap<>();

        LocalDate now = LocalDate.now();
        // 格式化为yyyy-MM-dd字符串
        String format = now.minusDays(days-1).format(DateTimeFormatter.ISO_LOCAL_DATE);

        LambdaQueryWrapper<SysVisits> wrapper = new LambdaQueryWrapper<SysVisits>()
                .ge(SysVisits::getPublishTime, format);
        List<SysVisits> list = sysVisitsService.list(wrapper);


//        QueryWrapper<SysVisits> queryWrapper = new QueryWrapper<SysVisits>()
//                .select("IFNULL(sum(visits), 0) AS visits");
//        SysVisits one = sysVisitsService.getOne(queryWrapper);


        if(list.size() == days) {
            map.put("sumCount",0);
            map.put("visits", list);
            return ResultUtil.success(map);
        }

        List<SysVisits> listMap = new ArrayList<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        SysVisits sysVisits;
        int sumCount =0;
        for(int i=1;i<days + 1;i++){
            String format1 = now.minusDays(days-i).format(DateTimeFormatter.ISO_LOCAL_DATE);
            List<SysVisits> list1 = list.stream().filter(f -> df.format(f.getPublishTime()).equals(format1)).toList();
            if(list1.isEmpty()){
                sysVisits = new SysVisits();
                sysVisits.setVisits(0);
                sysVisits.setPublishTime(new SimpleDateFormat("yyyy-MM-dd").parse(format1));
                listMap.add(sysVisits);
            }else {
                sumCount += list1.getFirst().getVisits();
                listMap.add(list1.getFirst());
            }
        }

        map.put("sumCount",sumCount);
        map.put("visits", listMap);

        return  ResultUtil.success(map);
    }


    @Operation(summary = "增加系统访问量")
    @GetMapping("/increaseTraffic")
    public void increaseTraffic() {
        sysVisitsService.incrementField();
    }


    @Operation(summary = "获取京沪巡查里程和次数信息")
    @GetMapping("/getpatrolInfo")
    public Result<Map<String,Object>> getpatrolInfo(@RequestParam(value = "days",required = false,defaultValue = "7") int days) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        LocalDate now = LocalDate.now();
        // 格式化为yyyy-MM-dd字符串
        String format = now.minusDays(days).format(DateTimeFormatter.ISO_LOCAL_DATE);

        QueryWrapper<PatrolInfo> wrapper = new QueryWrapper<>();
        wrapper.select("SUM(total_task_count) as total_task_count","SUM(total_mileage) as total_mileage","patrol_date");
        wrapper.ge("patrol_date",format);
        wrapper.groupBy("patrol_date").orderByDesc("patrol_date");
        List<PatrolInfo> list = patrolInfoService.list(wrapper);


        Map<String,Object> map = new HashMap<>();

        if(list.size() == days) {
            map.put("totalTaskCount",list.stream().mapToInt(PatrolInfo::getTotalTaskCount).sum());
            map.put("totalMileage", list.stream().mapToDouble(PatrolInfo::getTotalMileage).sum());
            map.put("patrolInfo", list);
            return ResultUtil.success(map);
        }


        PatrolInfo  patrolInfo;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 1; i <= days; i++) {
            LocalDate date = now.minusDays(i);
            String format1 = date.format(formatter);
            List<PatrolInfo> list1 = list.stream().filter(f -> df.format(f.getPatrolDate()).equals(format1)).toList();
            if(list1.isEmpty()){
                patrolInfo = new PatrolInfo();
                patrolInfo.setTotalTaskCount(0);
                patrolInfo.setTotalMileage(0.00);
                patrolInfo.setPatrolDate(df.parse(format1));
                list.add(patrolInfo);
            }
        }



//        for(int i=1;i<days + 1;i++){
//            String format1 = now.minusDays(days-i).format(DateTimeFormatter.ISO_LOCAL_DATE);
//            List<PatrolInfo> list1 = list.stream().filter(f -> df.format(f.getPatrolDate()).equals(format1)).toList();
//            if(list1.isEmpty()){
//                patrolInfo = new PatrolInfo();
//                patrolInfo.setTotalTaskCount(0);
//                patrolInfo.setTotalMileage(0.00);
//                patrolInfo.setPatrolDate(df.parse(format1));
//                list.add(patrolInfo);
//            }
//        }






        map.put("totalTaskCount",list.stream().mapToInt(PatrolInfo::getTotalTaskCount).sum());
        map.put("totalMileage", list.stream().mapToDouble(PatrolInfo::getTotalMileage).sum());
        map.put("patrolInfo", list.stream().sorted(Comparator.comparing(PatrolInfo::getPatrolDate).reversed()).toList());
        return ResultUtil.success(map);
    }


}
